home *** CD-ROM | disk | FTP | other *** search
- /*
- This code is NOT from Berkley, but FROM ME :-)
- Very stupid Arexx ping.
- Don't use it to ping localhost or you would ROTFL.
-
- Usage: ping <HOST> [SIZE/N] [NUM/N] [QUICK/S]
-
- HOST the host name to ping
- SIZE the size of the imcp echo packet
- NUM the number of packet to send - 0 means continuos
- QUICK don't delay, send fast
- */
-
- if ~show("L","rexxsupport.library") then
- if ~addlib("rexxsupport.library",0,-30) then do
- say "no rexxsupport.library"
- exit
- end
- if ~show("L","rxsocket.library") then
- if ~addlib("rxsocket.library",0,-30) then do
- say "no rxsocket.library"
- exit
- end
- if ~show("L","rmh.library") then
- if ~addlib("rmh.library",0,-30) then do
- say "no rmh.library"
- exit
- end
-
- prg = ProgramName("NOEXT")
-
- /** read and parse arguments **/
- if ~RMH_ReadArgs("HOST/A,SIZE/K/N,NUM/K/N,QUICK/S") then do
- call PrintFault(IoErr(),prg)
- exit
- end
-
- addr = resolve(parm.0.value)
- if addr=="-1" then call err "no host <"parm.0.value">"
-
- host=parm.0.value
- if parm.1.flag then
- if parm.1.value>7 & parm.1.value<8000 then dataSize=parm.1.value
- else call err("SIZE must be >7 and <8000")
- else dataSize=56
-
- if parm.2.flag then
- if parm.2.value>0 then numPkt=parm.2.value
- else call err("NUM must be positive")
- else numPkt=1E10
-
- wait=~parm.3.flag
-
- break=0
- signal on BREAK_C
-
- /** resolve host name **/
- sin.addrAddr=resolve(host)
- if sin.addrAddr=="-1" then call err("HOST not found")
-
- /** create a RAW ICMP socket **/
- sock=socket("INET","RAW","ICMP")
- if sock<0 then call err("no socket")
-
- /** socket must NOT blocking **/
- call IOCtlSocket(sock,"FIONBIO",1)
-
- /** we need an ID to recognize our icmp **/
- ourID=right(x2c(pragma("ID")),2)
- min=1E10
- max=0
- avg=0
- nrec=0
- ntrans=0
-
- /** create a timer **/
- t=CreateTimer()
- timSig=TimerSignal(t)
-
- if numPkt==1E10 then ps=""
- else ps=" Num:" numPkt
- say Upper(PRG) host "("sin.addrAddr"):" dataSize "data bytes" ps
-
- /** we go:
- wait_for_packet_or_time_to_send
- readpacket if any
- sendpacket if time
- **/
- call StartTimer(t,wait)
- call sendPacket(dataSize)
- sel.read.0=sock
- go=ntrans<numPkt | numPkt==1
- do while go
-
- res=WaitSelect("SEL",,,timSig)
- if res~=0 then call readPacket
-
- if and(sel.signals,timSig)~=0 then do
- call sendPacket(dataSize)
- if wait==0 then call WriteCH("STDOUT",".")
- call StartTimer(t,wait)
- end
- go=ntrans<numPkt
- end
- signal BREAK_C
- exit
-
- err:
- parse arg msg
- say prg":" msg
- exit
-
- pad: PROCEDURE
- parse arg string,len
- return copies(d2c(0),len-length(string)) || string
-
- d2m: PROCEDURE
- parse arg val,len
- return pad(d2c(val),len)
-
- sendPacket:
- parse arg dataSize
- /** here we create an ICMP echo packet **/
- pktf = ourID || d2m(ntrans,2)
- call GetSysTime("TV")
- pktf=pktf || d2m(tv.secs,4) || d2m(tv.micro,4) || copies("0"x,dataSize-8)
- temp="0800"x || "0000"x || pktf
- pkt="0800"x || d2c(InetCksum(temp)) || pktf
- res=SendTo(sock,pkt,0,"SIN")
- if res~=length(pkt) then do
- e=errno()
- if IsLibOn("TTCP") then es=e
- else es=ErrorString(e)
- call err("send error ("es")")
- end
- ntrans=ntrans+1
- return
-
- readPacket:
- /** here we read an ICMP packet and check if it is an ICMP
- echo-replay for us **/
- call GetSysTime("NOW")
- res=RecvFrom(sock,"BUFF",256)
- if res<0 then call err("recv error")
- parse var buff vhl +1 tos +1 len +2 id +2 off +2 ttl +1 rest
- hl=c2d(bitand(vhl,'F'x))*8
- buff=c2x(buff)
- parse var buff +hl type +2 code +2 cksum +4 id +4 seq +4 s +8 m +8 data
- if c2d(len)~=dataSize+8 | type~='00' | code~='00' | id~=c2x(ourID)
- then return
- old.secs=x2d(s)
- old.micro=x2d(m)
- call SubTime("NOW","OLD")
- time=now.secs*1000000+now.micro
- time=time%1000"."time//1000
- time=((time*100)%1)/100
- if wait==1 then
- say c2d(len) "bytes from" sin.AddrAddr": icmp_seq="x2d(seq) "ttl="c2d(ttl) "time="time "ms"
- nrec=nrec+1
- if time>max then max=time
- if time<min then min=time
- avg=avg+time
- return
-
- /** statistics **/
- BREAK_C:
- if break==1 | sigl<38 then call err("user break")
- if t~="T" then call StopTimer(t)
- break=1
- signal on BREAK_C
- if ntrans>nrec & max>0 then do
- res=WaitSelect("SEL",5)
- if res~=0 then call readPacket
- end
- if ntrans==0 then loss=100
- else loss=(ntrans-nrec)/ntrans*100
- say
- say "---" host "ping statistics ---"
- say ntrans "packets transmitted," nrec "packets received," loss"% packet loss"
- if nrec>0 then say "round-trip min/avg/max =" min"/"|| (((avg/nrec)*100)%1)/100 || "/"max "ms"
- exit
-